package com.rpay.web.service;

import com.rpay.common.dto.sms.SmsCodeDTO;
import com.rpay.common.dto.user.UserDTO;
import com.rpay.common.dto.user.UserRippleDTO;
import com.rpay.common.dto.user.UserTokenDTO;
import com.rpay.common.enums.PcsResultCode;
import com.rpay.common.enums.SmsCodeEnum;
import com.rpay.common.enums.SmsTypeEnum;
import com.rpay.common.exception.SmsException;
import com.rpay.common.exception.UserException;
import com.rpay.common.util.LoggerUtil;
import com.rpay.common.util.Md5Util;
import com.rpay.common.util.StringUtil;
import com.rpay.common.util.TraceIdGenerator;
import com.rpay.service.config.ServiceThreadLocal;
import com.rpay.service.sms.ISmsCodeService;
import com.rpay.service.user.*;
import com.rpay.web.param.LoginUser;
import com.rpay.web.param.RegisterUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Title：
 * Description
 *
 * @author fxg06 on 2018/4/30
 * @version 1.0
 */
@Service
public class UserService {

    @Autowired
    private IUserService iUserService;
    @Autowired
    private IUserTokenService iUserTokenService;
    @Autowired
    private ISmsCodeService iSmsCodeService;
    @Autowired
    private IUserTradeService iUserTradeService;
    @Autowired
    private IUserRippleService iUserRippleService;
    @Autowired
    private IUserIncomeService iUserIncomeService;

    @Value("${sms.code.invalidTime}")
    private long invalidTime;

    public UserDTO login(LoginUser loginUser) {
        UserDTO userDTO = iUserService.getUserByAccount(loginUser.getAccount());
        if (userDTO == null) {
            throw new UserException(PcsResultCode.USER_NOT_EXISTED);
        }
        if (!userDTO.getPassword().equals(Md5Util.encrypt(loginUser.getPassword()))) {
            throw new UserException(PcsResultCode.USER_PASSWORD_ERROR);
        }
        UserTokenDTO userTokenDTO = iUserTokenService.saveToken(userDTO.getId());
        userDTO.setAccessToken(userTokenDTO.getAccessToken());

        ServiceThreadLocal.setAccessToken(userTokenDTO.getAccessToken());
        ServiceThreadLocal.setUserId(userDTO.getId());

        return userDTO;
    }

    @Transactional
    public boolean register(RegisterUser registerUser) {
        UserDTO userDTO = iUserService.getUserByAccount(registerUser.getEmail());
        if (userDTO != null) {
            throw new UserException(PcsResultCode.USER_MAIL_EXISTED);
        }
        SmsCodeDTO smsCodeDTO = new SmsCodeDTO();
        smsCodeDTO.setVerifyType(SmsCodeEnum.REGISTER.getCode());
        smsCodeDTO.setType(SmsTypeEnum.MAIL.getCode());
        smsCodeDTO.setReceiver(registerUser.getEmail());
        smsCodeDTO.setCode(registerUser.getCode());
        SmsCodeDTO smsCode = iSmsCodeService.getSmsCode(smsCodeDTO);
        if (smsCode == null) {
            throw new SmsException(PcsResultCode.SMS_CODE_FAIL);
        }
        long failureTime = System.currentTimeMillis() - smsCode.getCreateTime().getTime();
        if (failureTime > invalidTime * 60 * 1000) {
            throw  new SmsException(PcsResultCode.SMS_CODE_EXPIRED);
        }

        UserDTO user = new UserDTO();

        //如果分享码不为空，表示该用户是通过别人分享注册的，那该用户自动加该团队
        if (!StringUtil.isBlank(registerUser.getShareCode())) {
            UserDTO parentUser = iUserService.getUserByShareCode(registerUser.getShareCode());
            //通过分享码查找父用户，不存在抛出异常
            if (parentUser == null) {
                throw new UserException(PcsResultCode.USER_SHARECODE_NOT_EXISTED);
            }
            user.setParentId(parentUser.getId());
            user.setTeamKey(parentUser.getTeamKey());
        } else {
            user.setTeamKey(TraceIdGenerator.getTraceId());
        }
        user.setEmail(registerUser.getEmail());
        user.setShareCode(StringUtil.getRandomString(10));
        user.setPassword(Md5Util.encrypt(registerUser.getPassword()));

        iUserService.saveUser(user);
        iSmsCodeService.updateValid(smsCode.getId());
        return true;
    }

    @Transactional
    public boolean bindPhone(String phone, String code) {
        UserDTO userDTO = iUserService.getUserByAccount(phone);
        if (userDTO != null) {
            throw new UserException(PcsResultCode.USER_PHONE_EXISTED);
        }

        SmsCodeDTO smsCodeDTO = new SmsCodeDTO();
        smsCodeDTO.setVerifyType(SmsCodeEnum.BIND.getCode());
        smsCodeDTO.setType(SmsTypeEnum.PHONE.getCode());
        smsCodeDTO.setReceiver(phone);
        smsCodeDTO.setCode(code);
        SmsCodeDTO smsCode = iSmsCodeService.getSmsCode(smsCodeDTO);
        if (smsCode == null) {
            throw new SmsException(PcsResultCode.SMS_CODE_FAIL);
        }
        long failureTime = System.currentTimeMillis() - smsCode.getCreateTime().getTime();
        if (failureTime > invalidTime * 60 * 1000) {
            throw  new SmsException(PcsResultCode.SMS_CODE_EXPIRED);
        }

        UserDTO user = new UserDTO();
        user.setPhone(phone);
        user.setId(ServiceThreadLocal.getUserId());
        iSmsCodeService.updateValid(smsCode.getId());
        iUserService.updateUser(user);

        return true;
    }

    public boolean modifyPwd(UserDTO user, SmsCodeDTO smsCodeDTO) {
        SmsCodeDTO smsCode = iSmsCodeService.getSmsCode(smsCodeDTO);
        if (smsCode == null) {
            throw new SmsException(PcsResultCode.SMS_CODE_FAIL);
        }
        long failureTime = System.currentTimeMillis() - smsCode.getCreateTime().getTime();
        if (failureTime > invalidTime * 60 * 1000) {
            throw  new SmsException(PcsResultCode.SMS_CODE_EXPIRED);
        }
        iUserService.updateUser(user);
        iSmsCodeService.updateValid(smsCode.getId());
        return true;
    }

    @Transactional
    public boolean saveUserRipple(UserDTO userDTO, UserRippleDTO userRippleDTO) {
        //保存用户合约
        userRippleDTO.setPrice(iUserTradeService.getRate());
        iUserRippleService.saveUserRipple(userRippleDTO);
        //更新用户余额
        userDTO.setRippleAmount(userDTO.getRippleAmount().subtract(userRippleDTO.getInvestAmount()));
        //如果用户可提现余额大于或等于用户总余额，那么用户可提现 余额就等于总余额
        if (userDTO.getBuyAmount().compareTo(userDTO.getRippleAmount()) != -1) {
            userDTO.setBuyAmount(userDTO.getRippleAmount());
        }
        iUserService.updateUser(userDTO);
        //用户升级
        iUserService.upgrade(userDTO.getId());
        //计算用户直推或逆推及团队收益
        iUserIncomeService.updateUserAchievement(userRippleDTO);
        return true;
    }


}
